package models

import (
	"errors"
	"github.com/beego/beego/v2/client/orm"
	"time"
	"weiboxs.com/new_h_glasses/utils"
)

type DoDoctorOrder struct {
	Id                  int64                `json:"id"`
	Archives            *Archives            `orm:"rel(fk);null;on_delete(do_nothing)" json:"archives"`
	Number              *DoDoctorOrderNumber `orm:"rel(fk);null;on_delete(do_nothing)" json:"number"`
	Inventory           *ErpInventory        `orm:"rel(fk);null;on_delete(do_nothing)" json:"-"`
	Inspects            *Inspects            `orm:"rel(fk);null;on_delete(do_nothing)" json:"-"`
	Guahao              *DoGuahao            `orm:"rel(fk);null;on_delete(do_nothing)" json:"-"`
	CollectfeesMiddleId int64                `json:"-"`
	DepartmentId        int64                `json:"department_id"`
	Status              int                  `json:"status"`     //医嘱状态0待发送1已发送2已回退3已退费4已作废
	PayStatus           int                  `json:"pay_status"` //支付状态0未支付1已支付2待退费3已退费
	DrugSend            int                  `json:"drug_send"`  //是否发药0否1是2退药
	Content             string               `json:"content"`
	ContentNumber       string               `json:"content_number"`
	ContentSpec         string               `json:"content_spec"`
	UsageTj             string               `json:"usage_tj"`
	UsagePc             string               `json:"usage_pc"`
	UsageMd             string               `json:"usage_md"`
	DosageJl            string               `json:"dosage_jl"`
	DosageTs            string               `json:"dosage_ts"`
	DosageZl            int64                `json:"dosage_zl"`
	Unit                string               `json:"unit"`
	Position            string               `json:"position"`
	DoctorName          string               `json:"doctor_name"`
	Entrust             string               `json:"entrust"`
	ProjectType         string               `json:"project_type"`
	ProjectId           int64                `json:"project_id" orm:"-"`
	UnitPrice           float64              `json:"unit_price"`
	TotalPrice          float64              `json:"total_price"`
	CreatedAt           int64                `json:"created_at"`
}

func (a *DoDoctorOrder) TableName() string {
	return DoDoctorOrderTableName()
}

func DoDoctorOrderTableName() string {
	return TableName("do_doctor_order")
}

//发送医嘱档案ID、挂号ID、医嘱数据、诊断
func SaveDoDoctorOrder(user BackendUser, archives_id, guahao_id int64, values []*DoDoctorOrder, diagnosis string) error {
	if archives_id == 0 || guahao_id == 0 || len(values) == 0 {
		return errors.New("参数错误")
	}
	to, _ := orm.NewOrm().Begin()
	//生成医嘱编号
	number, err := DoDoctorOrderNumberCreate(user.DepartmentId)
	if err != nil {
		return errors.New("医嘱编号生成失败" + err.Error())
	}
	paramsPrice := new(InventoryPriceQueryParams) //价格查询
	for k, _ := range values {
		value := values[k]
		value.Archives = &Archives{Id: archives_id}
		value.Guahao = &DoGuahao{Id: guahao_id}
		if value.ProjectType == "drug" { //类型为药品
			inventory := ErpInventoryFind(value.ProjectId)
			if inventory.Id == 0 {
				to.Rollback()
				return errors.New("找不到药品数据")
			}
			paramsPrice.DepId = inventory.DepartmentId
			paramsPrice.Product = inventory.Products
			paramsPrice.Snd = inventory.Snd
			price := GetInventoryPriceForQueryParams(paramsPrice);
			if price.Id > 0 {
				value.UnitPrice = price.SuggestedPrice
			} else {
				to.Rollback()
				return errors.New("[" + inventory.Products.FullName + "] 还未定价,请先定价")
			}
			value.Inventory = inventory
			value.Inspects = &Inspects{Id: 0}
		} else {
			inspects := InspectsFindOne(value.ProjectId)
			value.Inspects = inspects
			value.UnitPrice = inspects.UnitPrice
			value.Inventory = &ErpInventory{Id: 0}
		}
		value.Number = number
		value.CollectfeesMiddleId = 0
		value.TotalPrice = float64(value.DosageZl) * value.UnitPrice //计算总价格
		value.DepartmentId = user.DepartmentId
		value.DoctorName = user.RealName
		value.CreatedAt = time.Now().Unix()
		value.Status = 1
		value.PayStatus = 0
		values[k] = value

		//增加常用项目
		often := new(DoProjectOften)
		often.Inspects = value.Inspects
		often.Inventory = value.Inventory
		often.ProjectType = value.ProjectType
		often.DepartmentId = value.DepartmentId
		if err := DoProjectOftenSave(often); err != nil {
			to.Rollback()
			return errors.New("常用项目保存出错")
		}
	}
	//保存医嘱
	if _, err := to.InsertMulti(len(values), values); err != nil {
		to.Rollback()
		return errors.New("医嘱保存失败:" + err.Error())
	}
	//保存诊断
	if len(diagnosis) > 0 {
		diagn := new(DoDiagnosis)
		//诊断是否存在
		to.QueryTable(DoDiagnosisTableName()).Filter("archives_id", archives_id).Filter("guahao_id", guahao_id).One(diagn)
		diagn.CreatedAt = time.Now().Unix()
		diagn.Guahao = &DoGuahao{Id: guahao_id}
		diagn.Archives = &Archives{Id: archives_id}
		diagn.Content = diagnosis
		if _, err := DoDiagnosisSave(diagn); err != nil {
			to.Rollback()
			return errors.New("诊断保存失败:" + err.Error())
		}
	}
	//更新挂号状态
	if _, err := to.QueryTable(DoGuahaoTableName()).Filter("id", guahao_id).Update(orm.Params{"status": 1}); err != nil {
		to.Rollback()
		return errors.New("更新挂号失败:" + err.Error())
	}
	to.Commit()
	return nil
}

type DoDoctorOrderQueryParam struct {
	BaseQueryParam
	Archives    int64    `json:"archives_id"`
	Guahao      int64    `json:"guahao_id"`
	Department  int64    `json:"department"`
	PayStatus   string   `json:"pay_status"`
	Status      string   `json:"status"`
	DrugSend    string   `json:"drug_send"`
	ProjectType string   `json:"project_type"`
	StartDate   string   `json:"startdate"`
	EndDate     string   `json:"enddate"`
	Id          []string `json:"id"`
	Collectfees int64    `json:"collectfees"`
}

//查询医嘱列表
func DoDoctorOrderList(param *DoDoctorOrderQueryParam) []*DoDoctorOrder {
	query := orm.NewOrm().QueryTable(DoDoctorOrderTableName()).RelatedSel("Number")
	data := make([]*DoDoctorOrder, 0)
	cond := orm.NewCondition()
	cond = cond.And("department_id", param.Department)
	if param.Archives > 0 {
		cond = cond.And("archives_id", param.Archives)
	}
	if param.Guahao > 0 {
		cond = cond.And("guahao_id", param.Guahao)
	}
	if param.Collectfees > 0 {
		cond = cond.And("collectfees_id", param.Collectfees)
	}
	if len(param.PayStatus) > 0 {
		cond = cond.And("pay_status", param.PayStatus)
	}
	if len(param.Status) > 0 {
		cond = cond.And("status", param.Status)
	}
	if len(param.DrugSend) > 0 {
		cond = cond.And("drug_send", param.DrugSend)
	}
	if len(param.StartDate) > 0 && len(param.EndDate) > 0 {
		cond = cond.And("created_at__gte", utils.GetTimeParse(param.StartDate)).And("created_at__lte", utils.GetTimeParse(param.EndDate))
	}
	if len(param.ProjectType) > 0 {
		cond = cond.And("project_type", param.ProjectType)
	}
	if len(param.Id) > 0 {
		cond = cond.And("id__in", param.Id)
	}
	query.SetCond(cond).OrderBy("-number_id").Limit(-1).All(&data)

	return data
}

//医嘱操作,主操作医嘱状态
func DoctorOrderActionStatus(act_type int, id int64) error {
	model := new(DoDoctorOrder)
	o := orm.NewOrm()
	o.QueryTable(DoDoctorOrderTableName()).Filter("id", id).One(model)
	if model.Id == 0 {
		return errors.New("找不到医嘱数据")
	}
	//医嘱状态0待发送1已发送2已回退3已退费4已作废
	//支付状态0未支付1已支付2待退费3已退费
	switch act_type {
	case 1: //医嘱回退，条件：未支付、已发送
		if model.Status == 1 && model.PayStatus == 0 {
			model.Status = 2 //回退
		} else {
			return errors.New("医嘱状态不正确")
		}
		break
	case 2: //医嘱退费，条件：已支付、已发送
		if model.Status == 1 && model.PayStatus == 1 {
			model.Status = 3 //退费
		} else {
			return errors.New("医嘱状态不正确")
		}
		break
	case 3: //医嘱作废，条件：已发送或已退费、未支付或已退费
		if (model.Status == 1 || model.Status == 3) && (model.PayStatus == 0 || model.PayStatus == 3) {
			model.Status = 4 //作废
		} else {
			return errors.New("医嘱状态不正确")
		}
		break
	case 4: //重新发送，条件：已回退、未支付
		if model.Status == 2 && model.PayStatus == 0 {
			model.Status = 1 //已发送
		} else {
			return errors.New("医嘱状态不正确")
		}
		break
	}
	if _, err := o.Update(model); err != nil {
		return err
	}
	return nil
}

//获取待结帐记录
func GetWaitAccountUser(depid int64, kwd string) []*DoDoctorOrder {
	o := orm.NewOrm().QueryTable(DoDoctorOrderTableName()).RelatedSel("Archives")
	md := make([]*DoDoctorOrder, 0)
	o = o.Filter("department_id", depid).Filter("status", 1).Filter("pay_status", 0).GroupBy("archives_id")
	if len(kwd) > 0 {
		cond := orm.NewCondition()
		cond = cond.AndCond(cond.Or("Archives__mobile__contains", kwd).Or("Archives__pinyin__contains", kwd).Or("Archives__realname__contains", kwd))
		o = o.SetCond(cond)
	}
	o.All(&md)
	return md
}

//获取待发药记录
func GetWaitDispensing(depid int64, kwd string) []*DoDoctorOrder {
	o := orm.NewOrm().QueryTable(DoDoctorOrderTableName()).RelatedSel("Archives")
	md := make([]*DoDoctorOrder, 0)
	o = o.Filter("department_id", depid).Filter("status", 1).Filter("pay_status", 1).Filter("project_type", "drug").Filter("drug_send", 0).GroupBy("archives_id")
	if len(kwd) > 0 {
		cond := orm.NewCondition()
		cond = cond.AndCond(cond.Or("Archives__mobile__contains", kwd).Or("Archives__pinyin__contains", kwd).Or("Archives__realname__contains", kwd))
		o = o.SetCond(cond)
	}
	o.All(&md)
	return md
}
